package com.whfc.quality.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.whfc.base.param.AppFileExportParam;
import com.whfc.base.service.AppExportService;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.AppWarnModuleType;
import com.whfc.common.enums.AppWarnMsgChannel;
import com.whfc.common.exception.BizException;
import com.whfc.common.file.FileHandler;
import com.whfc.common.file.FilePathConfig;
import com.whfc.common.file.properties.FileExpirationRules;
import com.whfc.common.result.PageVO;
import com.whfc.common.result.PageVOUtil;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.*;
import com.whfc.entity.dto.msg.AppMsgToUserDTO;
import com.whfc.entity.dto.msg.PushMsgDTO;
import com.whfc.entity.dto.statistics.CheckDetailDTO;
import com.whfc.entity.dto.statistics.CheckStatisticsDTO;
import com.whfc.entity.dto.statistics.StatisticsProgressDTO;
import com.whfc.entity.dto.statistics.StatisticsProgressUnitDTO;
import com.whfc.entity.param.check.CheckSearchParam;
import com.whfc.fuum.service.SysDeptService;
import com.whfc.quality.dao.*;
import com.whfc.quality.dto.*;
import com.whfc.quality.entity.*;
import com.whfc.quality.enums.*;
import com.whfc.quality.param.*;
import com.whfc.quality.service.QualityCheckService;
import com.whfc.quality.service.QualityTaskService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClasssName QualityCheckServiceImpl
 * @Description 问题上报实现类
 * @Author hw
 * @Date 2020/7/30 9:09
 * @Version 1.0
 */
@DubboService(interfaceClass = QualityCheckService.class, version = "1.0.0", timeout = 5000)
public class QualityCheckServiceImpl implements QualityCheckService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @DubboReference(interfaceClass = AppExportService.class, version = "1.0.0")
    private AppExportService appExportService;

    @DubboReference(interfaceClass = SysDeptService.class, version = "1.0.0")
    private SysDeptService sysDeptService;

    @Autowired
    private QualityCheckMapper qualityCheckMapper;

    @Autowired
    private QualityCheckLogMapper qualityCheckLogMapper;

    @Autowired
    private QualityCheckUserMapper qualityCheckUserMapper;

    @Autowired
    private QualityCheckImgMapper qualityCheckImgMapper;

    @Autowired
    private QualityTaskItemExecMapper qualityTaskItemExecMapper;

    @Autowired
    private QualityTaskService qualityTaskService;

    @Autowired
    private QualityIssueTypeMapper issueTypeMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private FilePathConfig msFilePathConfig;

    @Autowired
    private FileHandler fileHandler;

    @Autowired
    private QualityIssueTypeMapper qualityIssueTypeMapper;

    private JSONObject pdfConfig;

    private final static String EXPORT_IMG_TEMPLATE = "<img src='%s' />";

    private final static String QUALITY_FILE_DESC = "质量上报";

    private final static String HTML_TEMPLATE_PATH = "pdfTemp/qualityCheckTemp.html";

    private final static String PDF_CONFIG_PATH = "pdfConfig/config.json";

    @PostConstruct
    public void info() throws IOException {
        ClassPathResource resource = new ClassPathResource(PDF_CONFIG_PATH);
        InputStream templateFileInputStream = resource.getInputStream();
        String pdfConfigStr = new String(FileUtil.readData(templateFileInputStream));
        if (StringUtils.isNotEmpty(pdfConfigStr)) {
            pdfConfig = JSONObject.parseObject(pdfConfigStr);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCheck(QualityCheckParam qualityCheckParam) throws BizException {
        logger.info("新增问题上报信息 QualityCheckParam：{}", qualityCheckParam.toString());

        //参数校验
        if (UrgencyLevel.parseValue(qualityCheckParam.getUrgency()) == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "紧急程度编码不存在");
        }
        if (qualityCheckParam.getCheckUsers().stream().distinct().count() < qualityCheckParam.getCheckUsers().size()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "质量问题上报用户信息重复");
        }
        if (qualityCheckParam.getPartId() == null) {
            qualityCheckParam.setPartId(-1);
        }
        if (qualityCheckParam.getIssueTypeId() == null) {
            qualityCheckParam.setIssueTypeId(-1L);
            qualityCheckParam.setIssueTypeName("手动录入");
        }
        if (qualityCheckParam.getIssueId() == null) {
            qualityCheckParam.setIssueId(-1L);
        }

        //开始保存质量问题主表
        Date rectifyStartTime = new Date();
        Date rectifyEndTime = qualityCheckParam.getRectifyDuration();
        QualityCheck qualityCheck = new QualityCheck();
        BeanUtils.copyProperties(qualityCheckParam, qualityCheck);
        qualityCheck.setRectifyStartTime(rectifyStartTime);
        qualityCheck.setRectifyEndTime(rectifyEndTime);
        qualityCheck.setCheckTime(rectifyStartTime);
        qualityCheck.setState(QualityCheckState.TO_BE_RECTIFIED.getValue());
        qualityCheck.setOverdue(OverdueStatus.NOT_OVERDUE.getValue());
        qualityCheck.setCheckUserId(qualityCheckParam.getCheckUserId());
        qualityCheck.setCheckUserName(qualityCheckParam.getCheckUserName());
        qualityCheckMapper.insertSelective(qualityCheck);

        //开始保存质量问题记录相关人员和质量问题流程处理
        QualityCheckLog checkLog = insertCheckUserAndLog(qualityCheckParam, qualityCheck);

        //处理图片
        if(!CollectionUtils.isEmpty(qualityCheckParam.getImgUrls())) {
            for (String imgUrl : qualityCheckParam.getImgUrls()) {
                QualityCheckImg checkImg = new QualityCheckImg();
                checkImg.setCheckId(qualityCheck.getId());
                checkImg.setLogId(checkLog.getId());
                checkImg.setImgUrl(imgUrl);
                qualityCheckImgMapper.insertSelective(checkImg);
            }
        }

        //报警消息
        QualityCheckDTO qualityCheckDTO = new QualityCheckDTO();
        BeanUtils.copyProperties(qualityCheck, qualityCheckDTO);
        qualityCheckDTO.setCheckId(qualityCheck.getId());
        generateMessage(qualityCheckDTO, qualityCheckParam.getCheckUsers());

        //检查任务更新
        Integer execId = qualityCheckParam.getTaskExecId();
        if (execId != null) {
            QuailTaskCompleteParam param = new QuailTaskCompleteParam();
            for (QualityCheckUserParam userParam : qualityCheckParam.getCheckUsers()) {
                if (QualityCheckUserType.REPORTER.getValue().equals(userParam.getType())) {
                    param.setUserName(userParam.getUserName());
                    param.setUserId(userParam.getUserId());
                }
            }
            param.setLocation(qualityCheckParam.getAddress());
            param.setLng(qualityCheckParam.getLng());
            param.setLat(qualityCheck.getLat());
            param.setExecId(qualityCheckParam.getTaskExecId());
            param.setCheckResult("隐患问题");
            param.setImgUrls(qualityCheckParam.getImgUrls());
            qualityTaskService.complete(param);
        }
    }

    @Override
    public void delCheck(Integer checkId) throws BizException {
        logger.info("删除质量问题检查记录, checkId:{}", checkId);
        qualityCheckMapper.logicDel(checkId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCheckLog(QualityCheckLogParam qualityCheckLogParam) throws BizException {
        logger.info("问题处理流程 QualityCheckLogParam：{}", qualityCheckLogParam.toString());
        QualityCheck check = qualityCheckMapper.selectByPrimaryKey(qualityCheckLogParam.getCheckId());
        verifyCheckLog(qualityCheckLogParam, check);
        if (!QualityOptionType.RECTIFY.getValue().equals(qualityCheckLogParam.getOpType()) && QualityOptionResult.QUALIFIED.getValue().equals(qualityCheckLogParam.getOpResult())) {
            //如果状态不为整改并且合格的情况下，在复查的时候质量问题状态为待核验，在核验的情况差问题质量状态为完成
            if (QualityOptionType.REVIEW.getValue().equals(qualityCheckLogParam.getOpType())) {
                List<QualityCheckUserDTO> dtos = qualityCheckUserMapper.selectQualityCheckUserDTOList(check.getId(), QualityOptionType.VERIFY.getValue());
                if (dtos.isEmpty()) {
                    check.setState(QualityCheckState.SUCCESS.getValue());
                } else {
                    check.setState(QualityCheckState.TO_BE_VERIFIED.getValue());
                }
            } else if (QualityOptionType.VERIFY.getValue().equals(qualityCheckLogParam.getOpType())) {
                check.setState(QualityCheckState.SUCCESS.getValue());
            }
        } else {
            //如果状态为整改时或不合格时，在整改状态下质量问题状态改为待复查，在复查状态下不合格时状态改为待整改(复查不合格)，在审核状态下不合格时状态改为待整改(核验不合格)
            if (QualityOptionType.RECTIFY.getValue().equals(qualityCheckLogParam.getOpType())) {
                check.setState(QualityCheckState.TO_BE_REVIEWED.getValue());
            } else if (QualityOptionType.REVIEW.getValue().equals(qualityCheckLogParam.getOpType())) {
                check.setState(QualityCheckState.UNQUALIFIED_REVIEW.getValue());
            } else if (QualityOptionType.VERIFY.getValue().equals(qualityCheckLogParam.getOpType())) {
                check.setState(QualityCheckState.UNQUALIFIED_VERIFY.getValue());
            }
        }

        QualityCheckLog checkLog = new QualityCheckLog();

        BeanUtils.copyProperties(qualityCheckLogParam, checkLog);
        Date opTime = new Date();
        checkLog.setOpTime(opTime);
        if (QualityOptionType.RECTIFY.getValue().equals(qualityCheckLogParam.getOpType())) {
            checkLog.setOpResult(null);
        }
        qualityCheckLogMapper.insertSelective(checkLog);
        if (qualityCheckLogParam.getImgUrls().size() > 0) {
            for (String imgUrl : qualityCheckLogParam.getImgUrls()) {
                QualityCheckImg checkImg = new QualityCheckImg();
                checkImg.setCheckId(check.getId());
                checkImg.setLogId(checkLog.getId());
                checkImg.setImgUrl(imgUrl);
                qualityCheckImgMapper.insertSelective(checkImg);
            }
        }
        qualityCheckMapper.updateByPrimaryKey(check);
        //发送消息
        generateMessage(qualityCheckLogParam, check, opTime);
    }

    @Override
    public QualityCheckListDTO list(QualityCheckListParam qualityCheckListParam) throws BizException {
        logger.info("质量问题上报列表 QualityCheckListParam：{}", qualityCheckListParam.toString());
        Integer[] type = {QualityCheckUserType.RECTIFIER.getValue(), QualityCheckUserType.REVIEWER.getValue(), QualityCheckUserType.VERIFIER.getValue()};

        //全部

        //我上报的

        //需要我处理

        List<QualityCheckDTO> list = qualityCheckMapper.selectByDeptId(qualityCheckListParam);
        QualityCheckListDTO qualityCheckListDTO = new QualityCheckListDTO();
        qualityCheckListDTO.setCheckList(list);
        qualityCheckListDTO.setReportNum(qualityCheckMapper.countReport(qualityCheckListParam));
        QualityCheckListParam allNumCheckListParam = new QualityCheckListParam();
        BeanUtils.copyProperties(qualityCheckListParam, allNumCheckListParam);
        allNumCheckListParam.setType(null);
        qualityCheckListDTO.setAllNum(qualityCheckMapper.selectByDeptId(allNumCheckListParam).size());
        for (QualityCheckDTO qualityCheckDTO : qualityCheckListDTO.getCheckList()) {
            qualityCheckDTO.setImgUrlList(qualityCheckImgMapper.selectByCheckId(qualityCheckDTO.getCheckId(), QualityCheckUserType.REPORTER.getValue(), null));
            qualityCheckDTO.setRectifyImgUrlList(qualityCheckImgMapper.selectByCheckId(qualityCheckDTO.getCheckId(), QualityCheckUserType.RECTIFIER.getValue(), null));
            qualityCheckDTO.setRectifyUserName(qualityCheckUserMapper.selectUserNamesByType(qualityCheckDTO.getCheckId(), QualityCheckUserType.RECTIFIER.getValue()));
        }
        if (Arrays.equals(type, qualityCheckListParam.getType())) {
            return screeningCheckList(qualityCheckListParam, list, qualityCheckListDTO, true);
        }
        calculatePage(list, qualityCheckListParam, qualityCheckListDTO);
        qualityCheckListParam.setType(type);
        qualityCheckListDTO.setDisposeNum(screeningCheckList(qualityCheckListParam, qualityCheckMapper.selectByDeptId(qualityCheckListParam), new QualityCheckListDTO(), false).getCheckList().size());

        return qualityCheckListDTO;
    }

    @Override
    public List<QualityCheckDTO> dayLogList(QualityCheckListParam qualityCheckListParam) throws BizException {
        List<QualityCheckDTO> list = qualityCheckMapper.selectByDeptId(qualityCheckListParam);
        for (QualityCheckDTO qualityCheckDTO : list) {
            qualityCheckDTO.setImgUrlList(qualityCheckImgMapper.selectByCheckId(qualityCheckDTO.getCheckId(), QualityCheckUserType.REPORTER.getValue(), null));
            qualityCheckDTO.setRectifyImgUrlList(qualityCheckImgMapper.selectByCheckId(qualityCheckDTO.getCheckId(), QualityCheckUserType.RECTIFIER.getValue(), null));
        }
        return list;
    }

    @Override
    public QualityCheckDescDTO desc(Integer checkId) throws BizException {
        logger.info("质量问题上报详情 checkId：{}", checkId);
        QualityCheckDescDTO checkDescDTO = qualityCheckMapper.selectById(checkId);
        QualityIssueType qualityIssueType = issueTypeMapper.selectByIssueTypeId(checkDescDTO.getIssueTypeId());
        if(null == qualityIssueType){
            checkDescDTO.setIssueTypeName("其他");
        }else{
            checkDescDTO.setIssueTypeName(qualityIssueType.getName());
        }

        checkDescDTO.setImgUrlList(qualityCheckImgMapper.selectByCheckId(checkId, QualityOptionType.REPORT.getValue(), checkDescDTO.getLogId()));
        List<QualityCheckLogDTO> logList = qualityCheckLogMapper.selectByCheckId(checkId);
        for (QualityCheckLogDTO logListDTO : logList) {
            logListDTO.setImgUrlList(qualityCheckImgMapper.selectByCheckId(checkId, logListDTO.getOpType(), logListDTO.getLogId()));
        }
        checkDescDTO.setLogList(logList);
        checkDescDTO.setUserList(qualityCheckUserMapper.selectByCheckId(checkId));
        return checkDescDTO;
    }

    @Override
    public List<QualityCheckDescDTO> descByIds(List<Integer> checkIds) throws BizException{
        if (CollectionUtils.isEmpty(checkIds)) {
            return new ArrayList<>();
        }
        List<QualityCheckDescDTO> checkDescDTOList= qualityCheckMapper.selectByIds(checkIds);
        checkDescDTOList.forEach(checkDescDTO->{
            QualityIssueType qualityIssueType = issueTypeMapper.selectByIssueTypeId(checkDescDTO.getIssueTypeId());
            if(null == qualityIssueType){
                checkDescDTO.setIssueTypeName("其他");
            }else{
                checkDescDTO.setIssueTypeName(qualityIssueType.getName());
            }
        });

        List<QualityCheckLogDTO> logList = qualityCheckLogMapper.selectByCheckIds(checkIds);
        Map<Integer, List<QualityCheckLogDTO>> logMap = logList.stream().collect(Collectors.groupingBy(QualityCheckLogDTO::getCheckId));

        List<QualityCheckUserDTO> userList = qualityCheckUserMapper.selectByCheckIds(checkIds);
        Map<Integer, List<QualityCheckUserDTO>> userMap = userList.stream().collect(Collectors.groupingBy(QualityCheckUserDTO::getCheckId));
        checkDescDTOList.forEach(s->{
            s.setLogList(logMap.get(s.getId()));
            s.setUserList(userMap.get(s.getId()));
        });
        return checkDescDTOList;
    }

    @Override
    public QualityCheckStatisticalDTO statistical(Integer deptId, Integer userId, Date startTime, Date endTime, Integer channel) throws BizException {
        logger.info("质量问题上报统计分析 deptId：{},startTime:{},endTime:{},channel:{}", deptId, startTime, endTime, channel);
        QualityCheckStatisticalDTO qualityCheckStatisticalDTO = new QualityCheckStatisticalDTO();
        qualityCheckStatisticalDTO.setGeneral(0L);
        qualityCheckStatisticalDTO.setRectified(0L);
        qualityCheckStatisticalDTO.setReviewed(0L);
        qualityCheckStatisticalDTO.setSuccess(0L);
        qualityCheckStatisticalDTO.setUnqualified(0L);
        qualityCheckStatisticalDTO.setUrgency(0L);
        qualityCheckStatisticalDTO.setVerified(0L);
        List<QualityCheckIssueStatisticalDTO> qualityCheckIssueStatisticalDTOS = qualityCheckMapper.selectIssueByCheckTime(deptId, userId, startTime, endTime);
        qualityCheckIssueStatisticalDTOS.forEach(qualityCheckIssueStatisticalDTO -> {
            QualityIssueType qualityIssueType = qualityIssueTypeMapper.selectByIssueTypeId(qualityCheckIssueStatisticalDTO.getIssueTypeId());
            if(null == qualityIssueType){
                qualityCheckIssueStatisticalDTO.setIssueName("其他");
            }else{
                qualityCheckIssueStatisticalDTO.setIssueName(qualityIssueType.getName());
            }
        });
        qualityCheckStatisticalDTO.setIssue(qualityCheckIssueStatisticalDTOS);
        qualityCheckStatisticalDTO.setPart(qualityCheckMapper.selectPartByCheckTime(deptId, userId, startTime, endTime));
        // 设置一般的用户统计数
        qualityCheckStatisticalDTO.setGeneralUserList(qualityCheckMapper.selectByCheckTimeAndUrgency(deptId, UrgencyLevel.GENERAL.getValue(), startTime, endTime));
        // 设置紧急的用户统计数
        qualityCheckStatisticalDTO.setUrgencyUserList(qualityCheckMapper.selectByCheckTimeAndUrgency(deptId, UrgencyLevel.URGENCY.getValue(), startTime, endTime));

        List<Map<String, Long>> mapList = qualityCheckMapper.selectByStateAndCheckTime(deptId, userId, startTime, endTime);
        for (Map<String, Long> map : mapList) {
            if (QualityCheckState.TO_BE_RECTIFIED.getValue().equals(map.get("state"))) {
                qualityCheckStatisticalDTO.setRectified(map.get("num"));
            } else if (QualityCheckState.TO_BE_REVIEWED.getValue().equals(map.get("state"))) {
                qualityCheckStatisticalDTO.setReviewed(map.get("num"));
            } else if (QualityCheckState.UNQUALIFIED_VERIFY.getValue().equals(map.get("state")) || QualityCheckState.UNQUALIFIED_REVIEW.getValue().equals(map.get("state"))) {
                qualityCheckStatisticalDTO.setUnqualified(qualityCheckStatisticalDTO.getUnqualified() + (map.get("num")));
            } else if (QualityCheckState.TO_BE_VERIFIED.getValue().equals(map.get("state"))) {
                qualityCheckStatisticalDTO.setVerified((map.get("num")));
            } else if (QualityCheckState.SUCCESS.getValue().equals(map.get("state"))) {
                qualityCheckStatisticalDTO.setSuccess((map.get("num")));
            }
        }
        List<Map<String, Long>> urgencyMapList = qualityCheckMapper.selectByUrgencyAndCheckTime(deptId, userId, startTime, endTime);
        for (Map<String, Long> map : urgencyMapList) {
            if (UrgencyLevel.URGENCY.getValue().equals(map.get("urgency"))) {
                qualityCheckStatisticalDTO.setUrgency((map.get("num")));
            } else if (UrgencyLevel.GENERAL.getValue().equals(map.get("urgency"))) {
                qualityCheckStatisticalDTO.setGeneral((map.get("num")));
            }
        }
        List<Date> dateList = null;
        if (channel == 1) {
            dateList = DateUtil.getDayList(DateUtil.addDays(startTime, -30), startTime);
        } else if (channel == 2) {
            dateList = DateUtil.getMonthListBetween(DateUtil.addMonth(startTime, -11), startTime);
        } else {
            dateList = DateUtil.getDayList(startTime, endTime);
        }
        List<QualityCheckMonthStatisticalDTO> monthStatisticals = new ArrayList<>();
        for (Date date : dateList) {
            if (date.getTime() <= System.currentTimeMillis()) {
                QualityCheckMonthStatisticalDTO monthStatisticalDTO = new QualityCheckMonthStatisticalDTO();
                monthStatisticalDTO.setDate(date);
                monthStatisticalDTO.setNum(qualityCheckMapper.selectByCheckTime(deptId, userId, date, channel));
                monthStatisticals.add(monthStatisticalDTO);
            }
        }
        qualityCheckStatisticalDTO.setMonth(monthStatisticals);
        return qualityCheckStatisticalDTO;
    }

    @Override
    public List<Integer> getCheckIds() throws BizException {
        return qualityCheckMapper.selectCheckIdAll();
    }

    @Override
    public void updateOverdue(List<Integer> checkIds) throws BizException {
        qualityCheckMapper.updateOverdue(checkIds);
    }

    @Override
    public QualityLogDTO qualityLog(Integer deptId, Date date) throws BizException {
        logger.info("问题日志，deptId：{},date:{}", deptId, date);
        Date startTime = DateUtil.getDateBegin(date);
        Date endTime = DateUtil.getDateEnd(date);
        List<QualityUserNumDTO> questionList = qualityCheckMapper.selectUserNum(deptId, date);
        Integer questionNum = questionList.stream().mapToInt(QualityUserNumDTO::getNum).sum();
        List<QualityUserNumDTO> checkList = qualityTaskItemExecMapper.selectUserNum(deptId, date);
        List<QualityIssueNumDTO> issueList = qualityCheckMapper.selectIssueNum(deptId, startTime, endTime);
        checkList = checkList.stream().filter(qualityUserNumDTO -> StringUtils.isNotEmpty(qualityUserNumDTO.getUserName())).collect(Collectors.toList());
        Integer checkNum = checkList.stream().mapToInt(QualityUserNumDTO::getNum).sum();
        QualityLogDTO qualityLogDTO = new QualityLogDTO();
        qualityLogDTO.setAllNum(questionNum + checkNum);
        qualityLogDTO.setQuestionNum(questionNum);
        qualityLogDTO.setCheckNum(checkNum);
        qualityLogDTO.setCheckList(checkList);
        qualityLogDTO.setQuestionList(questionList);
        qualityLogDTO.setIssueList(issueList);
        return qualityLogDTO;
    }

    @Override
    public void qualityExport(List<Integer> qualityIds, Integer deptId) throws BizException {

        String fileDesc = QUALITY_FILE_DESC;
        String fileName = RandomUtil.getRandomFileName();
        String suffix = qualityIds.size() > 1 ? "zip" : "pdf";
        AppFileExportParam fileExport = new AppFileExportParam();
        fileExport.setDeptId(deptId);
        fileExport.setFileName(fileName);
        fileExport.setFileFormat(suffix.toUpperCase());
        fileExport.setFileState(0);
        fileExport.setFileDesc(fileDesc);
        Integer id = appExportService.install(fileExport);
        fileExport.setId(id);

        CompletableFuture.runAsync(() -> {

            String footer = null;
            String header = null;
            if (pdfConfig.containsKey(deptId.toString())) {
                JSONObject config = pdfConfig.getJSONObject(deptId.toString());
                footer = config.getString("footer");
                header = config.getString("header");
            }
            String deptName = sysDeptService.getDeptName(deptId);
            logger.info("质量问题导出,生成pdf文件开始.....");
            List<InputStream> iss = new ArrayList<>(qualityIds.size());
            for (Integer qualityId : qualityIds) {
                logger.info("安全问题导出,deptName:{},qualityId:{}", deptName, qualityId);
                QualityCheckDescDTO descDTO = desc(qualityId);
                JSONObject exportJson = getExportJson(descDTO);
                exportJson.put("deptName", deptName);
                ClassPathResource resource = new ClassPathResource(HTML_TEMPLATE_PATH);
                String html;
                try {
                    InputStream templateFileInputStream = resource.getInputStream();
                    File tempFile = FileUtil.copyTemplateFile(templateFileInputStream);
                    html = HtmlUtil.freeMarkerRender(exportJson, tempFile);
                    ByteArrayOutputStream arrayOutputStream = ItextPdfUtil.htmlToPdf(html, header, footer);
                    iss.add(new ByteArrayInputStream(arrayOutputStream.toByteArray()));
                    templateFileInputStream.close();
                } catch (Exception e) {
                    logger.error("质量pdf导出异常", e);
                }
            }
            logger.info("质量问题导出,生成pdf文件结束.....");

            InputStream is = null;
            if (suffix.equals("zip")) {
                try {
                    is = ZipUtil.zipPdfFile(iss);
                    logger.info("安全问题导出,生成zip压缩包成功.....");
                } catch (IOException e) {
                    logger.error("压缩文件失败", e);
                }
            } else {
                is = iss.get(0);
            }

            logger.info("质量问题导出,文件上传.....");
            String path = msFilePathConfig.getFilePath("quality/export", fileName, suffix);
            String upload = fileHandler.upload(path, is, FileExpirationRules.DAYS_7);

            logger.info("质量问题导出,更新导出记录.....");
            AppFileExportParam upFileExport = fileExport;
            upFileExport.setFileUrl(upload);
            upFileExport.setFileState(1);
            appExportService.update(upFileExport);
        });

    }

    @Override
    public QualityCheckScreenDTO qualityCheckScreenStatistical(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("检查统计,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        QualityCheckScreenDTO data = qualityCheckMapper.selectStatisticalByDeptId(deptId, startTime, endTime);
        Integer checkNum = qualityTaskItemExecMapper.selectNumByDeptId(deptId, startTime, endTime);
        data.setCheckNum(checkNum);
        return data;
    }

    @Override
    public QualityCheckScreenDTO qualityCheckTypeAnalysis(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("上报问题类别分析,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        QualityCheckScreenDTO data = new QualityCheckScreenDTO();
        List<QualityIssueNumDTO> list = qualityCheckMapper.selectIssueTypeNum(deptId, startTime, endTime);
        if (!list.isEmpty()) {
            Integer allNum = list.stream().mapToInt(QualityIssueNumDTO::getNum).sum();
            data.setQuestionNum(allNum);
            list.forEach(qualityIssueNumDTO -> {
                QualityIssueType qualityIssueType = issueTypeMapper.selectByIssueTypeId(qualityIssueNumDTO.getIssueTypeId());
                if(null == qualityIssueType){
                    qualityIssueNumDTO.setIssueName("其他");
                }else{
                    qualityIssueNumDTO.setIssueName(qualityIssueType.getName());
                }
                Double num = MathUtil.divide(qualityIssueNumDTO.getNum(), allNum, 4) * 100;
                Double percent = MathUtil.round(num, 2);
                qualityIssueNumDTO.setPercent(percent);
            });
        }
        data.setList(list);
        return data;
    }

    @Override
    public QualityCheckUnfinishedDTO qualityCheckUnfinished(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("未销问题分析,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        QualityCheckUnfinishedDTO data = qualityCheckMapper.selectUnfinishedByDeptId(deptId, startTime, endTime);
        Integer num = data.getAllNum();
        data.setGeneralIssuesPercent(0D);
        data.setUrgencyIssuesPercent(0D);
        data.setExceedPercent(0D);
        if (num != 0) {
            Double generalIssuesPercent = MathUtil.divide(data.getGeneralIssues(), num, 4) * 100;
            Double urgencyIssuesPercent = MathUtil.divide(data.getUrgencyIssues(), num, 4) * 100;
            Double exceedPercent = MathUtil.divide(data.getExceed(), num, 4) * 100;
            data.setGeneralIssuesPercent(MathUtil.round(generalIssuesPercent, 2));
            data.setUrgencyIssuesPercent(MathUtil.round(urgencyIssuesPercent, 2));
            data.setExceedPercent(MathUtil.round(exceedPercent, 2));
        }
        return data;
    }

    @Override
    public List<QualityCheckPartStatisticalDTO> qualityCheckPartAnalysis(Integer deptId, Date startTime, Date endTime) throws BizException {
        logger.info("上报问题部位分析,deptId:{},startTime:{},endTime:{}", deptId, startTime, endTime);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        return qualityCheckMapper.selectPartByCheckTime(deptId, null, startTime, endTime);
    }

    private JSONObject getExportJson(QualityCheckDescDTO descDTO) {
        JSONObject exportJson = JSONObject.parseObject(JSONObject.toJSONString(descDTO));
        setExportJsonParam(exportJson);
        String imgUrlString = setExportJsonImg(exportJson);
        exportJson.put("imgUrlList", imgUrlString);
        return exportJson;
    }

    private void setExportJsonParam(JSONObject json) {
        Integer state = json.getInteger("state");
        JSONArray logIndex = new JSONArray();
        JSONArray logList = json.getJSONArray("logList");
        JSONArray logJson = new JSONArray();
        logList.forEach(o -> {
            JSONObject log = (JSONObject) o;
            Integer opType = log.getInteger("opType");
            String opTime = DateUtil.formatDate(log.getDate("opTime"), DateUtil.DATE_TIME_FORMAT);
            log.put("opTime", opTime);
            String imgUrlList = setExportJsonImg(log);
            log.put("imgUrlList", imgUrlList);
            if (QualityCheckUserType.RECTIFIER.getValue().equals(opType) && json.containsKey("rectifyRequire")) {
                log.put("opTime", DateUtil.formatDate(json.getDate("rectifyTime"), DateUtil.DATE_FORMAT));
                log.put("rectifyRequire", json.getString("rectifyRequire"));
                log.put("opDesc", "已完成：已经按要求整改完成," + log.get("opDesc"));
            } else {
                Integer opResult = log.getInteger("opResult");
                if (QualityOptionResult.QUALIFIED.getValue().equals(opResult)) {
                    log.put("opDesc", "合格：" + log.get("opDesc"));
                }
            }
            if (!QualityCheckUserType.REPORTER.getValue().equals(opType)) {
                logIndex.add(opType);
                logJson.add(log);
            } else {
                json.put("checkTime", log.getString("opTime"));
            }
        });
        Integer[] process = QualityCheckState.process(state);
        if (process != null) {
            List<Integer> processList = Arrays.asList(process);
            logIndex.addAll(processList);
            JSONArray userList = json.getJSONArray("userList");
            userList.forEach(o -> {
                JSONObject user = (JSONObject) o;
                JSONObject log = new JSONObject();
                if (processList.contains(user.getInteger("type"))) {
                    log.put("opDesc", "未完成");
                    log.put("opType", user.getInteger("type"));
                    log.put("userName", user.getString("userName"));
                    logJson.add(log);
                }
            });
        }
        json.put("logList", logJson);
    }

    private String setExportJsonImg(JSONObject json) {
        if (json.containsKey("imgUrlList")) {
            JSONArray imgUrlList = json.getJSONArray("imgUrlList");
            StringBuffer imgUrlString = new StringBuffer();
            imgUrlList.forEach(o -> {
                String imgUrl = String.valueOf(o);
                imgUrlString.append(String.format(EXPORT_IMG_TEMPLATE, imgUrl));
            });
            return imgUrlString.toString();
        }
        return null;
    }

    /**
     * 生成消息
     *
     * @param qualityCheckLogParam 操作日志
     * @param check                问题对象
     * @param opTime               操作时间
     * @return
     */
    private void generateMessage(QualityCheckLogParam qualityCheckLogParam, QualityCheck check, Date opTime) {
        Integer state = check.getState();
        if (QualityCheckState.SUCCESS.getValue().equals(state)) {
            //如果状态为已完成，就直接返回
            return;
        }
        Integer checkId = check.getId();
        String title = "";
        String content = "";
        List<QualityCheckUserDTO> list = new ArrayList<>();
        String time = DateUtil.formatDate(opTime, "yyyy-MM-dd HH:mm");
        if (QualityCheckState.UNQUALIFIED_REVIEW.getValue().equals(state)) {
            title = QualityMsgTemplate.UNQUALIFIED_REVIEW.getTitle();
            content = String.format(QualityMsgTemplate.UNQUALIFIED_REVIEW.getContent(), qualityCheckLogParam.getOpUserName(), time);
            list = qualityCheckUserMapper.selectQualityCheckUserDTOList(checkId, QualityOptionType.RECTIFY.getValue());
        } else if (QualityCheckState.UNQUALIFIED_VERIFY.getValue().equals(state)) {
            title = QualityMsgTemplate.UNQUALIFIED_VERIFY.getTitle();
            content = String.format(QualityMsgTemplate.UNQUALIFIED_VERIFY.getContent(), qualityCheckLogParam.getOpUserName(), time);
            list = qualityCheckUserMapper.selectQualityCheckUserDTOList(checkId, QualityOptionType.RECTIFY.getValue());
        } else if (QualityCheckState.TO_BE_REVIEWED.getValue().equals(state)) {
            title = QualityMsgTemplate.TO_BE_REVIEWED.getTitle();
            //获取上报人
            QualityCheckLog qualityCheckLog = qualityCheckLogMapper.selectByCheckIdAndOpType(checkId, QualityOptionType.REPORT.getValue());
            content = String.format(QualityMsgTemplate.TO_BE_REVIEWED.getContent(), qualityCheckLogParam.getOpUserName(), time, qualityCheckLog.getOpUserName());
            list = qualityCheckUserMapper.selectQualityCheckUserDTOList(checkId, QualityOptionType.REVIEW.getValue());
        } else if (QualityCheckState.TO_BE_VERIFIED.getValue().equals(state)) {
            title = QualityMsgTemplate.TO_BE_VERIFIED.getTitle();
            //获取整改人
            QualityCheckLog qualityCheckLog = qualityCheckLogMapper.selectByCheckIdAndOpType(checkId, QualityOptionType.RECTIFY.getValue());
            content = String.format(QualityMsgTemplate.TO_BE_VERIFIED.getContent(), qualityCheckLogParam.getOpUserName(), time, qualityCheckLog.getOpUserName());
            list = qualityCheckUserMapper.selectQualityCheckUserDTOList(checkId, QualityOptionType.VERIFY.getValue());
        }
        List<Integer> msgChannelList = new ArrayList<>();
        msgChannelList.add(AppWarnMsgChannel.WXMP.value());
        msgChannelList.add(AppWarnMsgChannel.MS.value());

        List<AppMsgToUserDTO> appMsgToUserDTOS = new ArrayList<>();
        for (QualityCheckUserDTO qualityCheckUserDTO : list) {
            AppMsgToUserDTO toUserDTO = new AppMsgToUserDTO();
            toUserDTO.setUserId(qualityCheckUserDTO.getUserId());
            toUserDTO.setNickName(qualityCheckUserDTO.getUserName());
            toUserDTO.setPhone(qualityCheckUserDTO.getUserPhone());
            appMsgToUserDTOS.add(toUserDTO);
        }

        PushMsgDTO pushMsgDTO = new PushMsgDTO();
        pushMsgDTO.setDeptId(check.getDeptId());
        pushMsgDTO.setTitle(title);
        pushMsgDTO.setContent(content);
        pushMsgDTO.setModuleType(AppWarnModuleType.QUALITY.value());
        pushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        pushMsgDTO.setMsgChannelList(msgChannelList);
        pushMsgDTO.setToUserList(appMsgToUserDTOS);
        pushMsgDTO.setTime(opTime);
        amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(pushMsgDTO));
    }

    /**
     * 发送报警消息
     *
     * @param qualityCheckDTO
     * @param checkUsers
     */
    private void generateMessage(QualityCheckDTO qualityCheckDTO, List<QualityCheckUserParam> checkUsers) {
        Integer checkId = qualityCheckDTO.getCheckId();
        Integer deptId = qualityCheckDTO.getDeptId();
        Date checkTime = qualityCheckDTO.getCheckTime();
        String checkUserName = qualityCheckDTO.getCheckUserName();
        //接收消息人员
        //整改人列表
        List<AppMsgToUserDTO> rectifyUserList = new ArrayList<>();
        //抄送人列表
        List<AppMsgToUserDTO> ccUserList = new ArrayList<>();
        for (QualityCheckUserParam checkUser : checkUsers) {
            AppMsgToUserDTO toUserDTO = new AppMsgToUserDTO();
            toUserDTO.setUserId(checkUser.getUserId());
            toUserDTO.setNickName(checkUser.getUserName());
            toUserDTO.setPhone(checkUser.getUserPhone());
            if (QualityCheckUserType.REPORTER.getValue().equals(checkUser.getType())) {
                checkUserName = checkUser.getUserName();
            }
            if (QualityCheckUserType.RECTIFIER.getValue().equals(checkUser.getType())) {
                rectifyUserList.add(toUserDTO);
            }
            if (QualityCheckUserType.CC.getValue().equals(checkUser.getType())) {
                ccUserList.add(toUserDTO);
            }
        }
        //接收通道
        List<Integer> msgChannelList = new ArrayList<>();
        msgChannelList.add(AppWarnMsgChannel.WXMP.value());
        msgChannelList.add(AppWarnMsgChannel.MS.value());
        //检查时间
        String time = DateUtil.formatDate(checkTime, "yyyy-MM-dd HH:mm");
        //发送消息给整改人
        String rectifyTitle = QualityMsgTemplate.RECTIFIED.getTitle();
        String rectifyContent = String.format(QualityMsgTemplate.RECTIFIED.getContent(), checkUserName, time);

        PushMsgDTO pushMsgDTO = new PushMsgDTO();
        pushMsgDTO.setDeptId(deptId);
        pushMsgDTO.setTitle(rectifyTitle);
        pushMsgDTO.setContent(rectifyContent);
        pushMsgDTO.setModuleType(AppWarnModuleType.QUALITY.value());
        pushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        pushMsgDTO.setMsgChannelList(msgChannelList);
        pushMsgDTO.setToUserList(rectifyUserList);
        pushMsgDTO.setTime(checkTime);
        //发送消息给抄送人
        String ccTitle = QualityMsgTemplate.SUCCESS.getTitle();
        String ccContent = String.format(QualityMsgTemplate.SUCCESS.getContent(), checkUserName, time);

        PushMsgDTO ccPushMsgDTO = new PushMsgDTO();
        ccPushMsgDTO.setDeptId(deptId);
        ccPushMsgDTO.setTitle(ccTitle);
        ccPushMsgDTO.setContent(ccContent);
        ccPushMsgDTO.setModuleType(AppWarnModuleType.QUALITY.value());
        ccPushMsgDTO.setMsgObjectId(String.valueOf(checkId));
        ccPushMsgDTO.setMsgChannelList(msgChannelList);
        ccPushMsgDTO.setToUserList(ccUserList);
        ccPushMsgDTO.setTime(checkTime);
        try {
            amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(pushMsgDTO));
            amqpTemplate.convertAndSend(QueueConst.PUSH_MSG_EXCHANGE, "", JSONUtil.toString(ccPushMsgDTO));
        } catch (Exception ex) {
            logger.error("", ex);
        }

    }

    /**
     * 查询问题列表分页
     *
     * @param list                  列表数据
     * @param qualityCheckListParam 列表请求查询数据
     * @param qualityCheckListDTO   列表返回数据
     * @return
     * @author hw
     * @date 2020/8/7 14:58
     **/
    private void calculatePage(List<QualityCheckDTO> list, QualityCheckListParam qualityCheckListParam, QualityCheckListDTO qualityCheckListDTO) {
        if (qualityCheckListParam.getPageSize() != null && qualityCheckListParam.getPageNum() != null) {
            int pages = (list.size() + qualityCheckListParam.getPageSize() - 1) / qualityCheckListParam.getPageSize();
            int subListStart = qualityCheckListParam.getPageNum().equals(1) ? 0 : ((qualityCheckListParam.getPageNum() - 1) * qualityCheckListParam.getPageSize());
            int subListEnd = subListStart + qualityCheckListParam.getPageSize();
            qualityCheckListDTO.setTotal(list.size());
            qualityCheckListDTO.setPages(pages);
            if (list.size() < subListStart) {
                qualityCheckListDTO.setCheckList(new ArrayList<>());
                return;
            }
            qualityCheckListDTO.setTotal(list.size());
            qualityCheckListDTO.setPages(pages);
            qualityCheckListDTO.setCheckList(list.subList(subListStart, subListEnd <= list.size() ? subListEnd : list.size()));
        }
    }

    /**
     * 筛选问题上报列表
     *
     * @param qualityCheckListParam 问题上报请求类
     * @param list                  问题上报数据
     * @param qualityCheckListDTO   问题上报返回类
     * @param type                  是否需要分页
     * @author hw
     * @date 2020/8/7 11:35
     **/
    private QualityCheckListDTO screeningCheckList(QualityCheckListParam qualityCheckListParam, List<QualityCheckDTO> list, QualityCheckListDTO qualityCheckListDTO, Boolean type) {
        List<QualityCheckDTO> newList = new ArrayList<>();
        Integer rectifiedNum = 0;
        Integer reviewedNum = 0;
        Integer verifiedNum = 0;
        for (QualityCheckDTO checkDTO : list) {
            if (QualityCheckState.TO_BE_RECTIFIED.getValue().equals(checkDTO.getState()) && QualityCheckUserType.RECTIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
                verifiedNum++;
            } else if (QualityCheckState.UNQUALIFIED_VERIFY.getValue().equals(checkDTO.getState()) && QualityCheckUserType.RECTIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
                verifiedNum++;
            } else if (QualityCheckState.UNQUALIFIED_REVIEW.getValue().equals(checkDTO.getState()) && QualityCheckUserType.RECTIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
                verifiedNum++;
            } else if (QualityCheckState.TO_BE_REVIEWED.getValue().equals(checkDTO.getState()) && QualityCheckUserType.REVIEWER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
                reviewedNum++;
            } else if (QualityCheckState.TO_BE_VERIFIED.getValue().equals(checkDTO.getState()) && QualityCheckUserType.VERIFIER.getValue().equals(checkDTO.getType())) {
                newList.add(checkDTO);
                rectifiedNum++;

            }
        }
        qualityCheckListDTO.setReviewedNum(reviewedNum);
        qualityCheckListDTO.setRectifiedNum(rectifiedNum);
        qualityCheckListDTO.setVerifiedNum(verifiedNum);
        qualityCheckListDTO.setDisposeNum(newList.size());
        if (type) {
            calculatePage(newList, qualityCheckListParam, qualityCheckListDTO);
        } else {
            qualityCheckListDTO.setCheckList(newList);
        }
        return qualityCheckListDTO;
    }

    /**
     * @param :qualityCheckParam
     * @param :qualityCheck
     * @Author hw
     * @Description 保存质量问题记录相关人员和质量问题流程处理
     * @Date 2020/7/30
     * @return: QualityCheckLog
     **/
    private QualityCheckLog insertCheckUserAndLog(QualityCheckParam qualityCheckParam, QualityCheck qualityCheck) {
        QualityCheckLog checkLog = null;
        for (QualityCheckUserParam userParam : qualityCheckParam.getCheckUsers()) {
            if (QualityCheckUserType.parseValue(userParam.getType()) == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "人员类型编码不存在");
            }
            //判断对应人员是否为上报人如果是上报人需要在质量问题流程表添加数据
            if (QualityCheckUserType.REPORTER.getValue().equals(userParam.getType())) {
                checkLog = new QualityCheckLog();
                checkLog.setCheckId(qualityCheck.getId());
                checkLog.setOpType(QualityCheckUserType.REPORTER.getValue());
                checkLog.setOpUserId(userParam.getUserId());
                checkLog.setOpUserName(userParam.getUserName());
                checkLog.setOpTime(new Date());
                qualityCheckLogMapper.insertSelective(checkLog);
            }
            //储存质量问题相关人员信息
            QualityCheckUser checkUser = new QualityCheckUser();
            checkUser.setCheckId(qualityCheck.getId());
            checkUser.setType(userParam.getType());
            checkUser.setUserId(userParam.getUserId());
            checkUser.setUserName(userParam.getUserName());
            checkUser.setUserPhone(userParam.getUserPhone());
            qualityCheckUserMapper.insertSelective(checkUser);
        }
        return checkLog;
    }

    /**
     * @Author hw
     * @Description 质量问题流程处理 前置校验
     * @Date 2020/7/31 9:53
     * @Param:
     * @Return:
     **/
    private void verifyCheckLog(QualityCheckLogParam qualityCheckLogParam, QualityCheck check) {
        if (check == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "没有查询到对应的质量问题");
        }
        QualityCheckUser checkUser = qualityCheckUserMapper.selectByCheckIdAndUserIdAndType(check.getId(), qualityCheckLogParam.getOpUserId(), qualityCheckLogParam.getOpType());
        if (checkUser == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前用户无法做该操作");
        }
        if (QualityOptionType.parseValue(qualityCheckLogParam.getOpType()) == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "操作类型错误");
        }
        if (!QualityOptionType.REPORT.getValue().equals(qualityCheckLogParam.getOpType()) && !QualityOptionType.RECTIFY.getValue().equals(qualityCheckLogParam.getOpType())) {
            if (qualityCheckLogParam.getOpResult() == null || QualityOptionResult.parseValue(qualityCheckLogParam.getOpResult()) == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "操作结果错误");
            }
        }
        //当质量整改问题已经存在则无法上报
        if (QualityOptionType.REPORT.getValue().equals(qualityCheckLogParam.getOpType())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法上报");
        }
        //当质量问题状态不为待整改、待整改(复查不合格)、待整改(核验不合格) 无法整改
        if (QualityOptionType.RECTIFY.getValue().equals(qualityCheckLogParam.getOpType()) && !QualityCheckState.UNQUALIFIED_REVIEW.getValue().equals(check.getState()) && !QualityCheckState.UNQUALIFIED_VERIFY.getValue().equals(check.getState()) && !QualityCheckState.TO_BE_RECTIFIED.getValue().equals(check.getState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法整改");
        }
        //当质量问题状态不为待复查时无法复查
        if (QualityOptionType.REVIEW.getValue().equals(qualityCheckLogParam.getOpType()) && !QualityCheckState.TO_BE_REVIEWED.getValue().equals(check.getState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法复查");
        }
        //当质量问题状态不为待核验时无法核验
        if (QualityOptionType.VERIFY.getValue().equals(qualityCheckLogParam.getOpType()) && !QualityCheckState.TO_BE_VERIFIED.getValue().equals(check.getState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "当前状态无法核验");
        }
    }


    @Override
    public StatisticsProgressDTO getStatisticsProgressDTO(Integer deptId, Integer userId, String startTime, String endTime) {

        //我的上报=隐患问题上报+巡查上报
        //隐患问题上报的
        CheckSearchParam csp = new CheckSearchParam();
        csp.setDeptId(deptId);
        csp.setUserId(userId);
        csp.setTypeList(Collections.singletonList(QualityCheckUserType.REPORTER.getValue()));
        Integer reportCount1 = qualityCheckMapper.selectCount(csp);

        //巡查上报
        CheckSearchParam tsp = new CheckSearchParam();
        tsp.setDeptId(deptId);
        tsp.setUserId(userId);
        tsp.setStateList(Collections.singletonList((TaskItemState.done.getValue())));
        Integer reportCount2 = qualityTaskItemExecMapper.selectCount(tsp);
        Integer reportCount = reportCount1 + reportCount2;

        //我的核验
        csp.setTypeList(Collections.singletonList(QualityCheckUserType.VERIFIER.getValue()));
        List<Integer> states = new ArrayList<>();
        states.add(QualityCheckState.TO_BE_VERIFIED.getValue());
        states.add(QualityCheckState.UNQUALIFIED_VERIFY.getValue());
        states.add(QualityCheckState.SUCCESS.getValue());
        csp.setStateList(states);
        csp.setWaitFix(false);
        Integer checkCount = qualityCheckMapper.selectCount(csp);

        List<Integer> sceneList = Stream.of(QualityCheckUserType.RECTIFIER.getValue(), QualityCheckUserType.REVIEWER.getValue(), QualityCheckUserType.VERIFIER.getValue()).collect(Collectors.toList());
        CheckSearchParam param = new CheckSearchParam();
        param.setDeptId(deptId);
        param.setUserId(userId);
        param.setStartTime(startTime);
        param.setEndTime(endTime);

        List<StatisticsProgressUnitDTO> taskProgressList = new ArrayList<>();
        for (Integer scene : sceneList) {

            param.setTypeList(Collections.singletonList(scene));

            if (QualityCheckUserType.RECTIFIER.getValue().equals(scene)) {
                List<Integer> stateList = new ArrayList<>();
                stateList.add(QualityCheckState.TO_BE_RECTIFIED.getValue());
                stateList.add(QualityCheckState.UNQUALIFIED_REVIEW.getValue());
                stateList.add(QualityCheckState.UNQUALIFIED_VERIFY.getValue());
                param.setStateList(stateList);
            } else if (QualityCheckUserType.REVIEWER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(QualityCheckState.TO_BE_REVIEWED.getValue()));
            } else if (QualityCheckUserType.VERIFIER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(QualityCheckState.TO_BE_VERIFIED.getValue()));
            }

            //待处理数量
            Integer waitFixCount = qualityCheckMapper.selectCount(param);

            //待整改-待复查-待核验-完成
            if (QualityCheckUserType.RECTIFIER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(QualityCheckState.TO_BE_REVIEWED.getValue()));
            } else if (QualityCheckUserType.REVIEWER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(QualityCheckState.TO_BE_VERIFIED.getValue()));
            } else if (QualityCheckUserType.VERIFIER.getValue().equals(scene)) {
                param.setStateList(Collections.singletonList(QualityCheckState.SUCCESS.getValue()));
            }

            //已处理数量
            Integer completeCount = qualityCheckMapper.selectCount(param);

            StatisticsProgressUnitDTO v = new StatisticsProgressUnitDTO();
            v.setScene(scene);
            v.setTotal(waitFixCount + completeCount);
            v.setCompleteCount(completeCount);
            taskProgressList.add(v);
        }
        StatisticsProgressDTO res = new StatisticsProgressDTO();
        res.setReportCount(reportCount);
        res.setCheckCount(checkCount);
        res.setTaskProgressList(taskProgressList);
        return res;
    }

    @Override
    public CheckStatisticsDTO getCheckStatistics(CheckSearchParam param) {

        Integer userId = param.getUserId();
        if (CollectionUtils.isEmpty(param.getTypeList())) {
            param.setUserId(null);
        }
        param.setWaitFix(false);
        //总数
        Integer questionCount = qualityCheckMapper.selectCount(param);

        param.setUserId(userId);
        //上报总数
        param.setTypeList(Collections.singletonList(QualityCheckUserType.REPORTER.getValue()));
        Integer reportTotalCount = qualityCheckMapper.selectCount(param);

        //复查不合格
        param.setTypeList(Collections.singletonList(QualityCheckUserType.REVIEWER.getValue()));
        param.setStateList(Collections.singletonList(QualityCheckState.UNQUALIFIED_REVIEW.getValue()));
        Integer reviewNoPassCount = qualityCheckMapper.selectCount(param);

        //核验不合格
        param.setTypeList(Collections.singletonList(QualityCheckUserType.VERIFIER.getValue()));
        param.setStateList(Collections.singletonList(QualityCheckState.UNQUALIFIED_VERIFY.getValue()));
        Integer verifiedNoPassCount = qualityCheckMapper.selectCount(param);

        //合格
        param.setStateList(Collections.singletonList(QualityCheckState.SUCCESS.getValue()));
        Integer passCount = qualityCheckMapper.selectCount(param);

        param.setWaitFix(true);
        //待整改
        param.setTypeList(Collections.singletonList(QualityCheckUserType.RECTIFIER.getValue()));
        param.setStateList(Collections.singletonList(QualityCheckState.TO_BE_RECTIFIED.getValue()));
        Integer fixCount = qualityCheckMapper.selectCount(param);

        //待复查
        param.setTypeList(Collections.singletonList(QualityCheckUserType.REVIEWER.getValue()));
        param.setStateList(Collections.singletonList(QualityCheckState.TO_BE_REVIEWED.getValue()));
        Integer reviewCount = qualityCheckMapper.selectCount(param);

        //待核验
        param.setTypeList(Collections.singletonList(QualityCheckUserType.VERIFIER.getValue()));
        param.setStateList(Collections.singletonList(QualityCheckState.TO_BE_VERIFIED.getValue()));
        Integer verifiedCount = qualityCheckMapper.selectCount(param);

        //巡查数量(巡查上报固定为未超期)
        param.setOverdueList(null);
        CheckSearchParam taskParam = new CheckSearchParam();
        taskParam.setUserId(userId);
        taskParam.setMeReport(param.getMeReport());
        taskParam.setDeptId(param.getDeptId());
        taskParam.setStartTime(param.getStartTime());
        taskParam.setEndTime(param.getEndTime());
        taskParam.setStateList(Collections.singletonList((TaskItemState.done.getValue())));

        Integer checkCount = qualityTaskItemExecMapper.selectCount(taskParam);

        CheckStatisticsDTO res = new CheckStatisticsDTO();
        res.setQuestionCount(questionCount);
        res.setFixCount(fixCount + reviewNoPassCount + verifiedNoPassCount);
        res.setReviewNoPassCount(reviewNoPassCount);
        res.setVerifiedNoPassCount(verifiedNoPassCount);
        res.setNoPassCount(reviewNoPassCount + verifiedNoPassCount);
        res.setReviewCount(reviewCount);
        res.setVerifiedCount(verifiedCount);
        res.setPassCount(passCount);
        res.setCheckCount(checkCount);
        res.setTotalCount(questionCount + checkCount);
        res.setReportTotalCount(reportTotalCount + checkCount);
        res.setVerifiedTotalCount(verifiedCount + verifiedNoPassCount + passCount);
        return res;
    }

    @Override
    public PageVO<CheckDetailDTO> getCheckPage(CheckSearchParam param) {
        PageVOUtil.startPage(param);
        List<CheckDetailDTO> list = qualityCheckMapper.selectCheckDetailDTOList(param);
        PageVOUtil.clearPage();
        for (CheckDetailDTO v : list) {
            v.setImgUrlList(qualityCheckImgMapper.selectByCheckId(v.getCheckId(), QualityCheckUserType.REPORTER.getValue(), null));
            v.setRectifyImgUrlList(qualityCheckImgMapper.selectByCheckId(v.getCheckId(), QualityCheckUserType.RECTIFIER.getValue(), null));
            v.setRectifyUserName(qualityCheckUserMapper.selectUserNamesByType(v.getCheckId(), QualityCheckUserType.RECTIFIER.getValue()));
        }
        return PageVOUtil.page(PageInfo.of(list));
    }

    @Override
    public void deleteBatch(List<Integer> idList) {
        if(CollectionUtils.isEmpty(idList)){
            return;
        }
        qualityCheckMapper.deleteBatch(idList);
    }

}
